package com.ynet.middleground.mobile.approve.service;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Calendar;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.ynet.core.exception.BusinessException;
import com.ynet.core.log.IfpLogger;
import com.ynet.file.service.FileService;
import com.ynet.file.starter.FileServiceConfiguration;
import com.ynet.middleground.mobile.approve.commom.ResponseResult;
import com.ynet.middleground.mobile.approve.constant.ErrorMessageConstant;
import com.ynet.middleground.mobile.approve.utils.CommUtils;

/**
 * @ClassName FileCenterService
 * @Description 文件相关
 * @Author liwq
 * @Date 2021/3/28 19:21
 * @Version 1.0
 */
@Service
public class FileCenterService {
    /**
     * oss服务工具类
     */
    @Autowired
    FileService fileService;
    /**
     * oss服务工具类
     */
    @Autowired
    FileServiceConfiguration fileServiceConfiguration;

    @Autowired
    CommUtils commUtils;

    /**
     * 删除上传附件
     * 
     * @param fileUrl 文件相对路径，例：
     * @return
     */
    public ResponseResult<String> fileDelete(String fileUrl) {
        ResponseResult<String> result = new ResponseResult<>();
        String fileName = null;
        if (StringUtils.isEmpty(fileUrl)) {
            throw new BusinessException(ErrorMessageConstant.ECUC0017_MESSAGE, ErrorMessageConstant.ECUC0017_CODE);
        }
        // 拿到文件名，例：李文全测试-1617009833612.txt
        fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        fileService.deleteFile("oss", fileName, commUtils.getOssBucketName());
        result.setData(fileName);
        return result;
    }

    /**
     * 文件下载
     * 
     * @param remoteFileUrl
     * @return
     */
    public void fileDownLoad(String remoteFileUrl, HttpServletResponse res) throws IOException {
        IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(), "文件下载,remoteFileUrl: {}",
            remoteFileUrl);
        BufferedInputStream bis = null;
        try {
            // step1: 获取文件后缀名
            String suffix = null;
            if (remoteFileUrl.lastIndexOf("/") == -1) {
                return;
            }
            String fileNameAndSuffix = remoteFileUrl.substring(remoteFileUrl.lastIndexOf("/") + 1);
            if (!StringUtils.isEmpty(fileNameAndSuffix)) {
                if (fileNameAndSuffix.lastIndexOf(".") == -1) {
                    return;
                }
                suffix = fileNameAndSuffix.substring(fileNameAndSuffix.lastIndexOf("."));
            }

            // step2: 根据文件URL,获取文件File
            remoteFileUrl = commUtils.getOssFullUrl(remoteFileUrl);
            File file = getFileByUrl(remoteFileUrl, suffix);
            if (file == null) {
                return;
            }

            // step3: 下载文件
            res.reset();
            if (".pdf".equals(suffix.toLowerCase())) {
                res.setContentType("application/pdf");
                res.setHeader("Content-Disposition", "inline; fileName=" + fileNameAndSuffix + ";filename*=utf-8''"
                    + URLEncoder.encode(fileNameAndSuffix, "UTF-8"));
            } else {
                res.setContentType("application/octet-stream");
                res.setHeader("Content-Disposition", "attachment; fileName=" + fileNameAndSuffix + ";filename*=utf-8''"
                    + URLEncoder.encode(fileNameAndSuffix, "UTF-8"));
            }
            res.setCharacterEncoding("utf-8");
            res.setContentLength((int)file.length());
            bis = new BufferedInputStream(new FileInputStream(file));
            byte[] buff = new byte[1024];
            OutputStream os = res.getOutputStream();
            int i = 0;
            while ((i = bis.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                bis.close();
            }
        }
    }

    /**
     * 文件下载之前的校验
     * 
     * @param remoteFileUrl
     * @return
     */
    public ResponseResult<String> validBeforeDownload(String remoteFileUrl) {
        ResponseResult<String> result = new ResponseResult<>();
        // step1：校验
        if (StringUtils.isEmpty(remoteFileUrl)) {
            throw new BusinessException(ErrorMessageConstant.ECUC0016_MESSAGE, ErrorMessageConstant.ECUC0016_CODE);
        }
        // 文件路径样例：zhongtai/ifp-mobile-approve-1616998731391.TXT
        String fileName = null;
        String suffix = null;
        String fileNameAndSuffix = remoteFileUrl.substring(remoteFileUrl.lastIndexOf("/") + 1);
        if (!StringUtils.isEmpty(fileNameAndSuffix)) {
            fileName = fileNameAndSuffix.substring(0, fileNameAndSuffix.lastIndexOf("."));
            suffix = fileNameAndSuffix.substring(fileNameAndSuffix.lastIndexOf("."));
        }
        if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(suffix)) {
            throw new BusinessException(ErrorMessageConstant.ECUC0016_MESSAGE, ErrorMessageConstant.ECUC0016_CODE);
        }
        // step1：返回结果
        return result;
    }

    /**
     * 根据文件URL获取文件File
     * 
     * @param fileUrl
     * @param suffix
     * @return
     */
    public File getFileByUrl(String fileUrl, String suffix) {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        BufferedOutputStream stream = null;
        InputStream inputStream = null;
        File file = null;
        try {
            URL imageUrl = new URL(fileUrl);
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            inputStream = conn.getInputStream();

            byte[] buffer = new byte[1024];
            int len = 0;

            while ((len = inputStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }

            file = File.createTempFile("pattern", suffix);
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            stream = new BufferedOutputStream(fileOutputStream);
            stream.write(outStream.toByteArray());

        } catch (Exception e) {
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (stream != null) {
                    stream.close();
                }
                outStream.close();
            } catch (Exception e) {
            }
        }
        return file;
    }

    /**
     * 文件上传
     * 
     * @param file
     * @param fileName
     * @param suffix
     * @return OSS路径
     */
    public ResponseResult<String> fileUpload(MultipartFile file, String fileName, String suffix)
        throws FileNotFoundException {
        ResponseResult<String> responseResult = new ResponseResult<>();
        String returnOss = null;

        // step1: 参数校验
        if (file == null || StringUtils.isEmpty(fileName) || StringUtils.isEmpty(suffix)) {
            throw new BusinessException(ErrorMessageConstant.ECUC0011_MESSAGE, ErrorMessageConstant.ECUC0011_CODE);
        }

        // step2: 文件类型&&大小校验
        if (!StringUtils.isEmpty(suffix)) {
            suffix = suffix.toUpperCase();
        }
        validFile(file, fileName, suffix);

        // step3: 上传到OSS
        File uploadFile = MultipartFileToFile(file);
        returnOss = fileService.uploadFile("oss", new FileInputStream(uploadFile),
            fileName + "-" + Calendar.getInstance().getTimeInMillis() + suffix.toLowerCase(),
            commUtils.getOssBucketName());

        // step4: 返回结果
        responseResult.setData(returnOss);
        return responseResult;
    }

    /**
     * 将MultipartFile转化为File
     * 
     * @param multiFile
     * @return
     */
    public static File MultipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            // 删除临时文件
            file.deleteOnExit();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取文件大小
     * 
     * @param multipartFile
     * @return 文件大小M
     */
    public double getFileSize(MultipartFile multipartFile) {
        if (multipartFile == null) {
            return 0;
        }
        // 上传文件的大小, 单位为字节.
        long len = multipartFile.getSize();
        // 转换成M
        double fileSize = 0;
        fileSize = (double)len / 1048576;
        return fileSize;
    }

    /**
     * 校验文件类型&&大小
     * 
     * @param file
     * @param fileName
     * @param fileExt
     */
    public void validFile(MultipartFile file, String fileName, String fileExt) {
        // step1:校验类型
        if (!".DOCS".equals(fileExt) && !".DOC".equals(fileExt) && !".XLS".equals(fileExt) && !".XLSX".equals(fileExt)
            && !".PPT".equals(fileExt) && !".PPTX".equals(fileExt) && !".PDF".equals(fileExt) && !".TXT".equals(fileExt)
            && !".WPS".equals(fileExt) && !".RAR".equals(fileExt) && !".ZIP".equals(fileExt) && !".7Z".equals(fileExt)
            && !".JPG".equals(fileExt) && !".JPEG".equals(fileExt) && !".PNG".equals(fileExt) && !".GIF".equals(fileExt)
            && !".SVG".equals(fileExt) && !".MP4".equals(fileExt) && !".AVI".equals(fileExt) && !".WMV".equals(fileExt)
            && !".RMVB".equals(fileExt) && !".RM".equals(fileExt) && !".MOV".equals(fileExt) && !".MP3".equals(fileExt)
            && !".M4A".equals(fileExt) && !".WMA".equals(fileExt) && !".AVI".equals(fileExt)) {
            throw new BusinessException(ErrorMessageConstant.ECUC0010_MESSAGE, ErrorMessageConstant.ECUC0010_CODE);
        }
        // step2: 校验文件大小
        // DOCX、DOC、XLS、XLSX、PPT、PPTX、PDF、TXT、WPS、RAR、ZIP、7Z主流办公文件格式和压缩文件格式的上传，文件大小不超过50M；
        // JPG、JPEG、PNG、GIF、SVG格式图片上传，图片大小不超过50M;
        // MP4、AVI、WMV、RMVB、RM、MOV格式视频上传,视频大小不超过100M；
        // MP3、M4A、WMA、AVI音频格式上传，音频大小不超过50M；
        double size = getFileSize(file);
        if (".DOCS".equals(fileExt) || ".DOC".equals(fileExt) || ".XLS".equals(fileExt) || ".XLSX".equals(fileExt)
            || ".PPT".equals(fileExt) || ".PPTX".equals(fileExt) || ".PDF".equals(fileExt) || ".TXT".equals(fileExt)
            || ".WPS".equals(fileExt) || ".RAR".equals(fileExt) || ".ZIP".equals(fileExt) || ".7Z".equals(fileExt)) {
            if (size > 50) {
                throw new BusinessException(ErrorMessageConstant.ECUC0012_MESSAGE, ErrorMessageConstant.ECUC0012_CODE);
            }
        }
        if (".JPG".equals(fileExt) || ".JPEG".equals(fileExt) || ".PNG".equals(fileExt) || ".GIF".equals(fileExt)
            || ".SVG".equals(fileExt)) {
            if (size > 50) {
                throw new BusinessException(ErrorMessageConstant.ECUC0012_MESSAGE, ErrorMessageConstant.ECUC0012_CODE);
            }
        }
        if (".MP4".equals(fileExt) || ".AVI".equals(fileExt) || ".WMV".equals(fileExt) || ".RMVB".equals(fileExt)
            || ".RM".equals(fileExt) || ".MOV".equals(fileExt)) {
            if (size > 100) {
                throw new BusinessException(ErrorMessageConstant.ECUC0013_MESSAGE, ErrorMessageConstant.ECUC0013_CODE);
            }
        }
        if (".MP3".equals(fileExt) || ".M4A".equals(fileExt) || ".WMA".equals(fileExt) || ".AVI".equals(fileExt)) {
            if (size > 50) {
                throw new BusinessException(ErrorMessageConstant.ECUC0012_MESSAGE, ErrorMessageConstant.ECUC0012_CODE);
            }
        }
        // step3: 校验文件名称&后缀
        String originalFilenameAndSuffix = file.getOriginalFilename();
        String oriFileName = null;
        String oriSuffix = null;
        if (!StringUtils.isEmpty(originalFilenameAndSuffix)) {
            oriFileName = originalFilenameAndSuffix.substring(0, originalFilenameAndSuffix.lastIndexOf("."));
            oriSuffix = originalFilenameAndSuffix.substring(originalFilenameAndSuffix.lastIndexOf("."));
        }
        if (!StringUtils.isEmpty(oriSuffix)) {
            oriSuffix = oriSuffix.toUpperCase();
        }
        if (!fileName.equals(oriFileName) || !fileExt.equals(oriSuffix)) {
            throw new BusinessException(ErrorMessageConstant.ECUC0017_MESSAGE, ErrorMessageConstant.ECUC0017_CODE);
        }
    }
}
